#include <iostream>
#include <string>
#include <cstring>
#include <unistd.h>
#include <memory>
#include <sys/types.h>
#include <sys/socket.h>

#include "TcpServer.hpp"
#include "HttpProtocol.hpp"

std::string SuffixToType(const std::string &suffix)
{
    if (suffix == ".html" || suffix == ".htm")
        return "text/html";
    else if (suffix == ".png")
        return "image/png";
    else if (suffix == ".jpg")
        return "image/jpeg";
    else
    {
        return "text/html";
    }
    // to do
}

std::string CodetoDesc(int code)
{
    switch (code)
    {
    case 200:
        return "OK";
    case 301:
        return "Moved Permanently";
    case 307:
        return "Temporary Redirect";
    case 403:
        return "Forbidden";
    case 404:
        return "Not Found";
    case 500:
        return "Internal Server Error";
    default:
        return "Unknown";
    }
}

std::string HandlerRequest(std::string &request)
{
    // 请求
    HttpRequest req;
    // 响应
    HttpResponse resp;
    // 反序列化
    req.Deserialize(request);
    // 解析请求行
    req.Parse();
    // 测试打印
    req.DebugHttp();
    int code = 200;
    std::string content = req.GetFileContent();
    // 用户请求的文件内容不为空就读取404
    if (content.empty())
    {
        code = 404;
        content = req.Get_404File();
    }
    
    // for test
    // code = 307;   // 临时重定向
    // code = 301;   // 永久重定向

    // 设置状态码
    resp.SetCode(code);
    // 设置状态码描述
    resp.SetDesc(CodetoDesc(code));
    // 用户请求的文件内容不为空
    // 构建状态行
    resp.MakeStatusLine();
    // 设置并添加对应的正文长度
    std::string content_len_str = "Content-Length: " + std::to_string(content.size()) + "\r\n"; // 正文长度
    resp.AddHeader(content_len_str);
    // 设置并添加对应的正文类型
    std::string content_type_str = "Content-Type: " + SuffixToType(req.Suffix()) + "\r\n"; // 正文类型
    resp.AddHeader(content_type_str);
    // 设置Cookie
    std::string namecookie = "Set-Cookie: username=zhangsan\r\n";  // 用户名
    resp.AddHeader(namecookie);
    std::string passwdcookie = "Set-Cookie: password=*******\r\n"; // 密码
    resp.AddHeader(passwdcookie);
    std::string statuscookie = "Set-Cookie: status=logined\r\n";   // 状态
    resp.AddHeader(statuscookie);

    // 添加进行重定向的报头
    // std::string location = "Location: https://www.bilibili.com/\r\n";
    // resp.AddHeader(location);
    // 添加正文
    resp.AddContent(content);
    // for test
    // std::cout << "Response: " << resp.Serialize() << std::endl;
    return resp.Serialize(); // 返回给用户一个完整的HTTP报文

    // for test
    // std::cout << "Suffix: " << req.Suffix() << "Content-Type: " << SuffixToType(req.Suffix()) << std::endl;

}

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        std::cout << "Usage: " << argv[0] << " port " << std::endl;
        return 1;
    }

    uint16_t localport = std::stoi(argv[1]);

    std::unique_ptr<TcpServer> tsvr(new TcpServer(localport, HandlerRequest));
    tsvr->Loop();
    return 0;
}